package cn.autumnorange.app.util.consumer.queue;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Slf4j
@ComponentScan({"cn.autumnorange.app.util.consumer.*"})
@Component
public class BusinessMessageReceiver {
  // ---------------------------业务队列常量定义-----------------------
  /** 业务交换机标识符 */
  public static final String BUSINESS_EXCHANGE_NAME = "dead-letter-business-exchange";
  /** 业务A队列 */
  public static final String BUSINESS_QUEUEA_NAME = "dead-letter-business-queuea";
  /** 业务B队列 */
  public static final String BUSINESS_QUEUEB_NAME = "dead-letter-business-queueb";

  /** 业务A队列与死信队列交换机绑定键 标识符 */
  public static final String DEAD_LETTER_QUEUEA_ROUTING_KEY =
      "dead-letter-deadletter-queuea-routingkey";
  /** 业务B队列与死信队列交换机绑定键 标识符 */
  public static final String DEAD_LETTER_QUEUEB_ROUTING_KEY =
      "dead-letter-deadletter-queueb-routingkey";
  /** 业务A死信队列名称 */
  public static final String DEAD_LETTER_QUEUEA_NAME = "dead-letter-deadletter-queuea";
  /** 业务B死信队列名称 */
  public static final String DEAD_LETTER_QUEUEB_NAME = "dead-letter-deadletter-queueb";
  // ---------------------------订单死信队列常量定义-----------------------
  /** 订单死信队列交换机标识符 属性值不能改 写死 */
  private static final String ORDER_DEAD_LETTER_QUEUE_KEY = "x-dead-letter-exchange";

  /** 订单死信队列交换机绑定键 标识符 属性值不能改，写死 */
  private static final String ORDER_DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";

  //    @RabbitListener(queues = BUSINESS_QUEUEA_NAME)
  @RabbitListener(
      bindings = {
        @QueueBinding(
            value = @Queue(value = BUSINESS_QUEUEA_NAME, durable = "true"),
            exchange = @Exchange(value =BUSINESS_EXCHANGE_NAME, type = ExchangeTypes.FANOUT))
      })
  public void receiveA(Message message, Channel channel) throws IOException {
    String msg = new String(message.getBody());
    log.info("收到业务消息A：{}", msg);
    boolean ack = true;
    Exception exception = null;
    try {
      if (msg.contains("deadletter")) {
        throw new RuntimeException("dead letter exception");
      }
    } catch (Exception e) {
      ack = false;
      exception = e;
    }
    if (!ack) {
      //            log.error("消息消费发生异常，error msg:{}", exception.getMessage(), exception);
      channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
    } else {
      channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
  }

  @RabbitListener(queues = BUSINESS_QUEUEB_NAME)
  public void receiveB(Message message, Channel channel) throws IOException {
    System.out.println("收到业务消息B：" + new String(message.getBody()));
    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
  }



    //标记消费者逻辑执行方法
    @RabbitListener(queues = {"routingqueueA"}) //监听队列 路由队列用队列名称
    public void emailMessage(String msg, Channel channel, Message message) throws IOException {

      try {
        log.info("Email direct --接收到消息：{}", msg);
        if (msg.contains("deadletter")) {
          throw new RuntimeException("dead letter exception");
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
      } catch (Exception e) {
        if (message.getMessageProperties().getRedelivered()) {
          log.error("消息已重复处理失败,拒绝再次接收...");
          //basicReject: 拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似 false表示消息不再重新进入队列
          channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
        } else {
          log.error("消息即将再次返回队列处理...");
          // basicNack:表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列
          channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
      }
    }
  //标记消费者逻辑执行方法
  @RabbitListener(queues = {"routingqueueB"}) //监听路由B队列 用队列名称
  public void routingQueueB(String msg, Channel channel, Message message) throws IOException {

    try {
      log.info("routingQueueB direct --接收到消息：{}", msg);

      channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    } catch (Exception e) {
      if (message.getMessageProperties().getRedelivered()) {
        log.error("消息已重复处理失败,拒绝再次接收...");
        //basicReject: 拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似 false表示消息不再重新进入队列
        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
      } else {
        log.error("消息即将再次返回队列处理...");
        // basicNack:表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列
        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
      }
    }
  }

//  // key = {"order.#","user.*"} 表示能消费 routingkey为  order.一个或多个字符   和  user.任意一个字符  的消息
//  @RabbitListener(queues = {"topic_queue_Name"})
//  public void topic_queue_Name(String msg,Channel channel, Message message) throws IOException {
//    try {
//      log.info("topic_queue_Name 接收到消息：{}", msg);
//
//      channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
//    } catch (Exception e) {
//      if (message.getMessageProperties().getRedelivered()) {
//        log.error("消息已重复处理失败,拒绝再次接收...");
//        //basicReject: 拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似 false表示消息不再重新进入队列
//        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
//      } else {
//        log.error("消息即将再次返回队列处理...");
//        // basicNack:表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列
//        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
//      }
//    }
//  }
//  // key = {"order.#","user.*"} 表示能消费 routingkey为  order.一个或多个字符   和  user.任意一个字符  的消息
//  @RabbitListener(bindings = {@QueueBinding(value = @Queue,exchange = @Exchange(name = "topic",type = ExchangeTypes.TOPIC),key = {"order#","user.*"})})
//  public void recevicel1(String message){
//    log.info("message1 = " + message);
//  }
//  // key = {"order.#","user.*"} 表示能消费 routingkey为  order.一个或多个字符   和  user.任意一个字符  的消息
//  @RabbitListener(bindings = {@QueueBinding(value = @Queue,exchange = @Exchange(name = "topic",type = ExchangeTypes.TOPIC),key = {"order2.#","user2.*"})})
//  public void recevicel2(String message){
//    log.info("message2 = " + message);
//  }
}
